package com.strongbj.iot.devices.ru.response.handle;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import com.alibaba.fastjson.JSON;
import com.strongbj.core.message.IMessageHandle;
import com.strongbj.core.util.ByteUtil;
import com.strongbj.core.util.ContextUtils;
import com.strongbj.iot.devices.ru.message.RUMessage;
import com.strongbj.iot.devices.ru.message.RuMessageFactory;
import com.strongbj.iot.devices.ru.response.entity.DoorInfoEntity;
import com.strongbj.iot.devices.ru.response.entity.UInfoEntity;
import com.strongbj.iot.devices.ru.response.entity.UInfoEntity.DevAddr;
import com.strongbj.iot.devices.ru.response.entity.UInfoEntity.UdevInfo;
import com.strongbj.iot.devices.ru.response.message.RUMQMessage;
import com.strongbj.iot.devices.ru.response.service.impl.CabinetCacheService;
import com.strongbj.iot.mq.producer.TopicSender;

import io.netty.channel.ChannelHandlerContext;

/**
 * U位信息的处理，将收到的U位信息放到cabinetService缓存服务中
 * 
 * @author yuzhantao
 *
 */
public class UInfoHandle implements IMessageHandle<RUMessage, Object> {
	private static Logger logger = LogManager.getLogger(UInfoHandle.class.getName());
	private TopicSender topicSender = (TopicSender) ContextUtils.getBean("topicSender");
	private CabinetCacheService cabinetService = (CabinetCacheService) ContextUtils.getBean("cabinetService");
	private SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
	/**
	 * 是否运行了重新盘点命令
	 */
	protected final static Map<String, Boolean> isRunReinventoryCommand = new ConcurrentHashMap<>();

	@Override
	public boolean isHandle(RUMessage t) {
		if (t.getType() == 6 || t.getType() == 8 || t.getType() == 1) {
			return true;
		} else {
			return false;
		}
	}

	/**
	 * 从RU1000获取U位信息并传递到MQ服务器
	 */
	@Override
	public Object handle(ChannelHandlerContext ctx, RUMessage t) {
		switch (t.getType()) {
		case 6:
			this.openOrCloseDoorHandle(t);
			break;
		case 1: // 重新盘点
		case 8:
			this.uInfoHandle(ctx, t);
			break;
		}
		return null;
	}

	/**
	 * 开关门处理，将开关门数据通过cabinetService类保存到内存中
	 * 
	 * @param msg
	 */
	private void openOrCloseDoorHandle(RUMessage msg) {
		String devAddr = bytesToHexString(msg.getAddress()).toUpperCase(); // 将设备地址的3byte转int
		logger.info("开始处理开关门信息,devCode={}", devAddr);
		this.cabinetService.setDoorState(devAddr, msg.getBody()[0]); // 将门更新信息记录到内存中

		// 发门信息到mq
		String json = this.doorInfoUpload(msg);
		topicSender.send("RU", json);
		logger.info("发送门信息到MQ:" + json);
	}

	/**
	 * U位信息处理,将收到的U位信息通过cabinetService类保存到内存中
	 * 
	 * @param msg
	 */
	private void uInfoHandle(ChannelHandlerContext ctx, RUMessage msg) {
		String devAddr = bytesToHexString(msg.getAddress()).toUpperCase(); // 将设备地址的3byte转int
		logger.info("开始处理U位扫描信息,devCode={}", devAddr);
		UInfoEntity entity = RUMessage2UInfoEntity(msg);
		Map<Byte, String> uInfoMap = new HashMap<>();
		for (DevAddr dev : entity.getDevAddrList()) {
			for (UdevInfo u : dev.getUdevInfo()) {
				uInfoMap.put(Integer.valueOf(u.getU()).byteValue(), u.getRfid());
			}
		}
		// 判断机柜是否可是推送
		if (cabinetService.checkCabinetInfoIsPush(devAddr, uInfoMap)) {
			cabinetService.updateScanUInfo(entity);
			try {
				String json = JSON.toJSONString(uInfoMap);
				logger.info("{}开关门U位上传符合漏盘算法检测，因此将数据保存到待发内存中 deviceCode:[{}]   json={}", dateFormat.format(new Date()),
						devAddr, json);
			} catch (Exception e) {
				e.printStackTrace();
			}
		} else {
			RuMessageFactory.sendReinventoryCommandToRU1000(ctx, devAddr); // 向RU1000下发盘点命令
				logger.info("{}开关门U位上传时，发现不符合漏盘算法检测，因此发送重盘命令 deviceCode:{}", dateFormat.format(new Date()), devAddr);
		}
			cabinetService.addCheckCabinetInfo(devAddr, uInfoMap);
			logger.info("{}添加开关门盘点数据到漏判队列 deviceCode:{}", dateFormat.format(new Date()), devAddr);
	}

	/**
	 * 开关门信息上传
	 * 
	 * @param message
	 * @return
	 */
	private String doorInfoUpload(RUMessage message) {
		String address = ByteUtil.byteArrToHexString(message.getAddress()).toUpperCase();
		DoorInfoEntity entity = new DoorInfoEntity();
		entity.setDevAddrCode(address);
		entity.setCdoorstate(String.valueOf(ByteUtil.byteToInt(message.getBody()[0])));
		RUMQMessage mes = new RUMQMessage();
		mes.setActioncode("reader008");
		mes.setGUID(String.valueOf(new Date().getTime()));
		mes.setRfidtype("RU1000");
		mes.setAwsPostdata(entity);
		return JSON.toJSONString(mes);
	}

	/**
	 * 对象转换
	 * 
	 * @param message
	 * @return
	 */
	private UInfoEntity RUMessage2UInfoEntity(RUMessage message) {
		UInfoEntity entity = new UInfoEntity();
		String address = ByteUtil.byteArrToHexString(message.getAddress()).toUpperCase();
		UInfoEntity.DevAddr devAddr = entity.new DevAddr();
		List<UInfoEntity.DevAddr> devAddrList = new ArrayList<UInfoEntity.DevAddr>();
		devAddr.setDevAddrCode(address);
		List<UInfoEntity.UdevInfo> udevInfo = new ArrayList<UInfoEntity.UdevInfo>();
		byte[] uInfo = message.getBody();
		for (int i = 1; i < uInfo.length; i = i + 11) {
			byte[] tagTemp = new byte[4];
			System.arraycopy(uInfo, i + 3, tagTemp, 0, 4);
			String tag = ByteUtil.byteArrToHexString(tagTemp);
			int u = ByteUtil.byteToInt(uInfo[i + 7]);
			UInfoEntity.UdevInfo info = entity.new UdevInfo();
			info.setRfid(tag);
			info.setU(u);
			udevInfo.add(info);
		}
		devAddr.setUdevInfo(udevInfo);
		devAddrList.add(devAddr);
		entity.setDevAddrList(devAddrList);
		return entity;
	}

	private static String bytesToHexString(byte[] src) {
		StringBuilder stringBuilder = new StringBuilder("");
		if (src == null || src.length <= 0) {
			return null;
		}
		for (int i = 0; i < src.length; i++) {
			int v = src[i] & 0xFF;
			String hv = Integer.toHexString(v);
			if (hv.length() < 2) {
				stringBuilder.append(0);
			}
			stringBuilder.append(hv);
		}
		return stringBuilder.toString();
	}
}
